package com.bgs.microservices.service.common.config;



import com.bgs.microservices.service.common.security.jwt.ExceptionHandlerFilter;
import com.bgs.microservices.service.common.security.jwt.JWTAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.web.filter.CorsFilter;

import static org.springframework.security.config.Customizer.withDefaults;

/**
 * @ClassName WebSecurityConfig
 * @Description Security 权限配置
 * @Author zcy
 * @Date 2023/3/27 10:28
 **/
@Configuration
public class WebSecurityConfig {

    /**
     * 自定登录失败做出的返回结果
     */
    @Autowired
    AuthenticationEntryPoint authExceptionEntryPoint;
    /**
     * 自定义登出处理逻辑
     */
    @Autowired
    LogoutSuccessHandler logoutSuccessHandler;

    /**
     * 捕获token异常fv
     */
    @Autowired
    ExceptionHandlerFilter exceptionHandlerFilter;

    /**
     * 声明密码加密方式
     * @return
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * 放行路径
     */
    private  static  final  String[]  AUTH_WHITELIST  =  {
            // -- swagger ui
            "/swagger-resources/**",
            "/swagger-ui.html",
            "/swagger-ui/swagger-ui.html",
            "/v3/api-docs/**",
            "/v2/api-docs",
            "/swagger-ui/**",
            "/webjars/**",
            "/images/**",
            "/js/**",
            "/webjars/**",
            "/druid/**",
            "druid/login.html",
            "/sysUser/code",
            "/doc.html",
            "/v3/api-docs",
            "/test/**"
    };

    /**
     * 注册 Security相关自定义过滤器
     * @param http
     * @return
     * @throws Exception
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((auth) -> {
                            try {
                                auth.requestMatchers(AUTH_WHITELIST).permitAll()
                                        .anyRequest().authenticated();
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        }
                        //异常处理(权限拒绝、登录失效等)
                ).exceptionHandling((exceptionHl) ->
                        //匿名用户访问无权限资源时的异常处理
                        exceptionHl.authenticationEntryPoint(authExceptionEntryPoint)
                ).logout((logout) ->
                        //登出成功处理逻辑
                        logout.logoutSuccessHandler(logoutSuccessHandler).permitAll()
                ).sessionManagement(sm ->
                        sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                ).csrf((csrf) ->
                        //禁用session
                        csrf.disable()
                )
                .httpBasic(withDefaults());
//        // 禁用缓存
//        http.headers().cacheControl();
        // 添加JWT过滤器
        http.addFilter(new JWTAuthenticationTokenFilter(authenticationManager(http)));
        // 注册异常捕获过滤器
        http.addFilterBefore(exceptionHandlerFilter, CorsFilter.class);
       return http.build();
    }
    /**
     * 注册自定义登录
     * @param httpSecurity
     * @return
     * @throws Exception
     */
    @Bean("authenticationManager")
    @Primary
    AuthenticationManager authenticationManager(HttpSecurity httpSecurity) throws Exception {
        AuthenticationManager authenticationManager = httpSecurity.getSharedObject(AuthenticationManagerBuilder.class)
                .build();
        return authenticationManager;
    }



}
